package com.example.ktdemo.span.view;

import android.content.Context;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.style.AbsoluteSizeSpan;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.List;

/**
 * author:li
 * date:2022/10/22
 * desc:span text view
 * 自定义span text view
 */
public class SpanTextView extends androidx.appcompat.widget.AppCompatTextView {
    private SpanTextViewListener mSpanTextListener;

    public SpanTextView(@NonNull Context context) {
        super(context);
        init();
    }

    public SpanTextView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public SpanTextView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        //设置启用span
        setMovementMethod(LinkClickMovementMethod.getInstance());
        //设置高亮颜色为透明
        setHighlightColor(Color.TRANSPARENT);
        //长按事件监听
        setOnLongClickListener(new OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                notifyLongClick(v);
                return true;
            }
        });
    }


    protected int dp2px(int dpValue) {
        return (int) getContext().getResources().getDisplayMetrics().density * dpValue;
    }

    //span 点击类-----------------------------------------------------------------------------------

    public interface ClickCusListener {
        <T extends SpanViewInfo> void onClick(View v, T info);
    }

    /**
     * 内部类，用于截获点击富文本后的事件
     */
    public class SpanClickable<T extends SpanViewInfo> extends ClickableSpan implements OnClickListener {
        private final ClickCusListener mListener;
        private T info;

        public SpanClickable(T info, ClickCusListener mListener) {
            this.mListener = mListener;
            this.info = info;
        }

        @Override
        public void onClick(View v) {
            v.clearFocus();
            if (mListener != null) {
                mListener.onClick(v, info);
            }
        }

        @Override
        public void updateDrawState(TextPaint ds) {
            ds.setColor(ds.getColor());
            ds.setUnderlineText(false);    //去除超链接的下划线
        }

    }

    //通知相关-----------------------------------------------------------------------------

    private void notifyLongClick(View v) {
        if (mSpanTextListener != null) {
            mSpanTextListener.LongClick(v);
        }
    }

    private <T extends SpanViewInfo> void notifyClick(View v, T t) {
        if (mSpanTextListener != null) {
            mSpanTextListener.click(v, t);
        }
    }


    //span 绘制----------------------------------------------------------------------------------


    /**
     * 绘制文字
     * 替换&nbsp为空格
     */
    private <T extends SpanViewInfo> void drawTxt(T spanTextInfo) {
        if (spanTextInfo == null || spanTextInfo.getText() == null ||
                TextUtils.isEmpty(spanTextInfo.getText().getText())) {
            return;
        }
        SpanViewInfo.TxtInfo txtInfo = spanTextInfo.getText();
        String text = txtInfo.getText().replaceAll("&nbsp;", " ");
        int size = dp2px(txtInfo.getSize());
        int color = txtInfo.getColor();

        SpannableString spanString = new SpannableString(text);

        ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(color);
        spanString.setSpan(foregroundColorSpan, 0, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        AbsoluteSizeSpan span = new AbsoluteSizeSpan(size);
        spanString.setSpan(span, 0, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        if (txtInfo.isBold()) {
            StyleSpan styleSpan = new StyleSpan(Typeface.BOLD);
            spanString.setSpan(styleSpan, 0, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }

        //点击事件-----------------------------------------------------------
        int clickEnd = text.length();
        if (clickEnd > 1) {
            clickEnd = clickEnd - 1;
        }
        spanString.setSpan(new SpanClickable<T>(spanTextInfo, new ClickCusListener() {
            @Override
            public <T extends SpanViewInfo> void onClick(View v, T info) {
                notifyClick(v, info);
            }
        }), 0, clickEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        append(spanString);
    }

    /**
     * 绘制图片
     */
    private <T extends SpanViewInfo> void drawPic(T spanPicInfo) {
        if (spanPicInfo == null || spanPicInfo.getPic() == null ||
                spanPicInfo.getPic().getPicId() == -1) {
            return;
        }
        SpanViewInfo.PicInfo picInfo = spanPicInfo.getPic();
        if (picInfo.getWidth() == 0 || picInfo.getHeight() == 0) {
            return;
        }

        int resId = picInfo.getPicId();
        Drawable picDrawable = null;
        try {
            picDrawable = getResources().getDrawable(resId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (picDrawable == null) {
            return;
        }
        int width = dp2px(picInfo.getWidth());
        int height = dp2px(picInfo.getHeight());
        int align = picInfo.getAlign();
        picDrawable.setBounds(0, 0, width, height);

        String totalText = "\t\t";

        SpannableStringBuilder spanString = new SpannableStringBuilder(totalText);

        VerticalImageSpan imgSpan = new VerticalImageSpan(picDrawable, align);
        spanString.setSpan(imgSpan, 0, spanString.length(),
                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        int imgStartSpan = spanString.getSpanStart(imgSpan);
        int imgEndSpan = spanString.getSpanEnd(imgSpan);
        ClickableSpan[] click_spans = spanString.getSpans(imgStartSpan, imgEndSpan, ClickableSpan.class);
        if (click_spans != null && click_spans.length != 0) {
            for (ClickableSpan c_span : click_spans) {
                spanString.removeSpan(c_span);
            }
        }
        spanString.setSpan(new SpanClickable<T>(spanPicInfo, new ClickCusListener() {
            @Override
            public <T extends SpanViewInfo> void onClick(View v, T info) {
                notifyClick(v, info);
            }
        }), imgStartSpan, imgEndSpan, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        append(spanString);
    }

    //外部调用方法----------------------------------------------------------------------------

    /**
     * 清楚缓存
     */
    public void clearCache() {
        if (getEditableText() != null) {
            getEditableText().clear();
            getEditableText().clearSpans();
            setText(null);
        }
    }

    /**
     * 设置数据
     */
    public <T extends SpanViewInfo> void setInfo(List<T> info) {
        if (info == null || info.size() == 0) {
            setText(null);
            return;
        }
        //遍历数据进行实现
        for (T t : info) {
            switch (t.getType()) {
                case 0:
                    //普通文字
                    drawTxt(t);
                    break;
                case 1:
                    //图片
                    drawPic(t);
                    break;
            }
        }
    }

    /**
     * 设置监听
     */
    public void setSpanTextViewListener(SpanTextViewListener listener) {
        this.mSpanTextListener = listener;
    }

    public void removeSpanTextViewListener() {
        this.mSpanTextListener = null;
    }


}
